package org.xiaozhou.chatgptcativen.domain.security.service;


import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import io.jsonwebtoken.*;
import org.apache.shiro.codec.Base64;
import org.slf4j.Logger;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

public class JwtUtil {

    private Logger logger = org.slf4j.LoggerFactory.getLogger(JwtUtil.class);

    // 创建默认的密钥和加密算法方式
    private static final String defaultBase64EncodedSecretKey = "[B@6d03e736";
    private static final SignatureAlgorithm defaultSignatureAlgorithm = io.jsonwebtoken.SignatureAlgorithm.HS256;

    private String base64EncodedSecretKey;
    private SignatureAlgorithm signatureAlgorithm;
    public JwtUtil(){
        this.base64EncodedSecretKey = defaultBase64EncodedSecretKey;
        this.signatureAlgorithm = defaultSignatureAlgorithm;
    }

    public JwtUtil(String secretKey, SignatureAlgorithm signatureAlgorithm){
        this.base64EncodedSecretKey = Base64.encodeToString(secretKey.getBytes());
        this.signatureAlgorithm = signatureAlgorithm;
    }


    public String encode(String issuer, long ttlMillis, Map<String, Object> claims){
        //如果claims为空的话，那就用默认的claims
        if (claims == null){
            claims = new HashMap<>();
        }

        long currentTimeMillis = System.currentTimeMillis();


        JwtBuilder builder = Jwts.builder()
                // 荷载部分
                .setClaims(claims)
                // 这个是JWT的唯一标识，一般设置成唯一的，这个方法可以生成唯一标识
                .setId(UUID.randomUUID().toString())//2.
                // 签发时间
                .setIssuedAt(new Date(currentTimeMillis))
                // 签发人，也就是JWT是给谁的（逻辑上一般都是username或者userId）
                .setSubject(issuer)
                .signWith(signatureAlgorithm, base64EncodedSecretKey);//这个地方是生成jwt使用的算法和秘钥

        if (ttlMillis >= 0){
            builder.setExpiration(new Date(currentTimeMillis + ttlMillis));
        }

        return builder.compact();
    }

    //解析token
    public Claims parseToken(String token) {
        return Jwts.parser()
                .setSigningKey(base64EncodedSecretKey)
                .parseClaimsJws(token)
                .getBody();
    }

    public boolean validate(String jwt) {
        try {
            Jws<Claims> claimsJws = Jwts.parser()
                    .setSigningKey(base64EncodedSecretKey)
                    .parseClaimsJws(jwt);
            return true;
        } catch (SignatureException e) {
            logger.info("Invalid JWT signature: {}" , e.getMessage());
        } catch (MalformedJwtException e) {
            logger.info("Invalid JWT token: {}" , e.getMessage());
        } catch (ExpiredJwtException e) {
            logger.info("JWT token is expired: {} " , e.getMessage());
        } catch (UnsupportedJwtException e) {
            logger.info("JWT token is unsupported: {}" , e.getMessage());
        } catch (IllegalArgumentException e) {
            logger.info("JWT claims string is empty: {}" , e.getMessage());
        }
        return false;
    }

}
